﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NCM_MSTest.Alg;

namespace NCM_MSTest
{
    [TestClass]
    [TestCategory("常微分方程的数值解")]
    public class 常微分方程的数值解
    {
        [TestMethod]
        public void Example_6_1_6_2_6_3()
        {
            var fxy = new Fxy((x, y) => -y + x + 1);
            var h = 0.1d;
            var iy = 1;
            var ix = 0;
            double[] xs = new double[]
            {
                0.1,0.2,0.3,0.4,0.5,
            };
            double[] xs1 = new double[]
            {
                0.1,0.2,0.3,0.4,0.5,
                0.6,0.7,0.8,0.9,1.0,
            };
            double[] _ys1 = new double[xs.Length];
            double[] _ys2 = new double[xs.Length];
            double[] _ys3 = new double[xs.Length];
            Console.WriteLine("改进的欧拉方法");
            OrdinaryDifferentialEquation.ImprovedEulerMethod(fxy, iy, ix, h, xs, out _ys1);
            Console.WriteLine("龙格库塔法");
            OrdinaryDifferentialEquation.Runge_Kutta(fxy, iy, ix, h, xs, out _ys2);
            Console.WriteLine("四阶阿达姆斯预估-校正法");
            OrdinaryDifferentialEquation.Adams(fxy, iy, ix, h, xs1, out _ys3);
        }

        /// <summary>
        /// 用四阶龙格库塔法
        /// y'_1 = y_2
        /// y'_2 = x*y_2+y_1
        /// y_1(0) = 1
        /// y_2(0) = 1
        /// </summary>
        [TestMethod]
        public void Example_6_4()
        {
            Fxyz f = new Fxyz((a, b, c) => c);
            Fxyz g = new Fxyz((a, b, c) => a * c + b);
            double x0 = 0;
            double y10 = 1;
            double y20 = 1;
            double h = 0.1;
            double xf = 1.0;
            double[] ys = new double[10];
            Console.WriteLine("方程组四阶龙格-库塔公式");
            OrdinaryDifferentialEquation.Runge_kutta_4(f, g, x0, y10, y20, xf, h, ys);
        }

        /// <summary>
        /// 二阶常微分方程四阶龙格库塔公式
        /// y'' = f(x,y,y'), x > x_0
        /// y(x_0) = y0
        /// y'(x_0) = y_0'
        /// </summary>
        [TestMethod]
        public void Example_6_5()
        {
            Fxy f = new Fxy((t, v) => (31500 - 0.39 * v * v) * 9.8 / (13500 - 180 * t) - 9.8);
            double t0 = 0;
            double y0 = 0;
            double v0 = 0;
            double h = 0.01;
            double tf = 60.0;
            double[] ys = new double[10];
            Console.WriteLine("二阶常微分方程四阶龙格库塔公式");
            OrdinaryDifferentialEquation.SecondOrder_Runge_kutta_4(f, t0, tf, y0, v0, h);
        }

        /// <summary>
        /// y''(x) + xy'(x)-xy(x)=2x
        /// y(0)=1,y(1)=0
        /// h=0.1
        /// x0=0.1,xf=0.9
        /// </summary>
        [TestMethod]
        public void Example_6_6()
        {
            Fxyz f1 = new Fxyz((x, y1, y2) => 2 * x + x * y1 - x * y2);
            Fxyz f2 = new Fxyz((x, y1, y2) => x * y1 - x * y2);
            double h = 0.1;
            double x0 = 0.0;
            double xf = 1.0;
            double[] ys;
            double y110 = 1.0d, y120 = 0;
            double y210 = 0.0d, y220 = 1.0;
            double y20 = 1.0;
            Console.WriteLine("化为初值问题的解法");
            OrdinaryDifferentialEquation.Runge_kutta_Border(f1, f2
                , h, x0, xf
                , y110, y120, y210, y220
                , y20
                , out ys);

            Console.WriteLine("边值问题的差分解法");
            F px = (x) => x;
            F qx = (x) => -x;
            F fx = (x) => 2 * x;
            double[] a=new double[11];
            double[] b=new double[11];
            double[] c=new double[11];
            double[] d=new double[11];
            int n = 11;
            OrdinaryDifferentialEquation.DifferenceMethod_TwoOrderBoundary(n, 0.1, 1.0, 0.0, a, b, c, d);
        }
    }
}
